#ifndef __FIXED_STRING_H_INCLUDED__
#define __FIXED_STRING_H_INCLUDED__

#include <glf/fstl/fixed_vector.h>

#include <string>

namespace glf {

template<typename T>
struct char_traits : public std::char_traits<T> {

	static int vsprintf(char* dst, size_t n, const char* fmt, va_list args) {
		return glf::Vsprintf_s(dst, n, fmt, args);
	}
	static int vsprintf(wchar_t* dst, size_t n, const wchar_t* fmt, va_list args) {
		GLF_ASSERT(false);
		return 0;
		//return glf::Vwprintf_s(dst, n, fmt, args);
	}
};

//doesnt work yet for wchar_t
template<typename T>
struct ci_traits : public char_traits<T> {
	static bool eq(T c1, T c2) { 
		return toupper(c1) == toupper(c2); 
	}

	static bool ne(T c1, T c2){ 
		return !eq(c1, c2); //toupper(c1) != toupper(c2); 
	}

	static bool lt(T c1, T c2) { 
		return toupper(c1) < toupper(c2); 
	}

    static const char* find(const T* s, int n, T a) {
		while(n-- > 0 && toupper(*s) != toupper(a)) {
			++s;
		}
		return s;
    }
	static int compare(const T* s1, const T* s2, size_t n) {
		for ( ; n > 0; s1++, s2++, --n) {
			if(ne(*s1, *s2)) {
				return lt(*s1, *s2);
			} else if (*s1 == 0) {
				return 0;
			}
		}
		return 0;
	}
};

template<size_t N, typename T=char, typename TRAITS=std::char_traits<T> >
struct fixed_string : public fixed_container<T, N> {
	static const size_t npos = size_t(-1);
	
	fixed_string() : 
		fixed_container<T,N>() {
	}
	fixed_string (const fixed_string& str) : 
		fixed_container<T,N>() {
		
		TRAITS::assign(this->first(), str.first(), N);
	}
	fixed_string (const fixed_string& str, size_t pos, size_t n = npos) : 
		fixed_container<T,N>() {
		TRAITS::assign(str.first(), pos, n);
	}
	fixed_string (const char * s, size_t n) : 
		fixed_container<T,N>() {
		TRAITS::assign(s, 0, n);
	}
	fixed_string (const char * s) : 
		fixed_container<T,N>() {
		TRAITS::assign(s, 0, npos);
	}
	fixed_string (size_t n, char c) : 
		fixed_container<T,N>() {
	}
	template<class InputIterator> 
	fixed_string (InputIterator begin, InputIterator end)  : 
		fixed_container<T,N>() {
		for(iterator<T> it = begin; it != end; ++it) {
			push_back(*it);
		}
	}

	~fixed_string() {
	}

	void sprintf(const T* fmt, ...) {
		va_list args;
		va_start(args, fmt);
		
		int written = TRAITS::vsprintf(this->first(), N, fmt, args);
		va_end(args);
		
		this->mSize = written;
	}
	void append_sprintf(size_t idx, const T* fmt, ...) {
		va_list args;
		va_start(args, fmt);
		int written = TRAITS::vsprintf(this->last(), N-idx, fmt, args);
		va_end(args);
		
		this->mSize += written;
	}
};

}

#endif